<template>
  <Button type="primary" @click="onConnect">{{ text }}</Button>
  <Modal
    v-model:open="visible"
    :title="title"
    :mask-closable="false"
    :keyboard="false"
    :destroy-on-close="true"
    :footer="false"
    width="50%"
    @cancel="onCancel"
  >
    <div class="w-full overflow-x-auto py-4">
      <template v-for="(item, idx) in items" :key="idx">
        <Divider orientation="left">{{ item.key }}</Divider>
        <Steps
          :items="item.values"
          :current="item.values.length - 1"
          size="small"
        />
      </template>
    </div>
  </Modal>
</template>

<script setup lang="tsx">
import { computed, ref } from 'vue';
import { useEventSource } from '@boeyo/hooks';
import { useUserStore } from '@boeyo/portal';
import { Button, Divider, Modal, Steps, StepsProps } from 'ant-design-vue';

interface Props {
  title: string;
  text: string;
  url: string;
  body: Record<string, any> | String;
  beforeConnect?: () => Promise<any>;
}

const userStore = useUserStore();
const props = withDefaults(defineProps<Props>(), {
  beforeConnect: () => Promise.resolve(),
});

const body = computed(() => {
  return typeof props.body === 'string'
    ? props.body
    : JSON.stringify(props.body);
});

const device = ref<Record<string, any>>({});
const items = computed<
  Array<{
    key: string;
    values: StepsProps['items'];
  }>
>(() => {
  return Object.keys(device.value).map((key) => {
    return {
      key: key,
      values: device.value[key].map((item) => {
        return {
          title: item.msg,
          description: item.date,
          status: getStatus(item.code),
        };
      }),
    };
  });
});

const getStatus = (code: number): StepsProps['status'] => {
  switch (code) {
    case 201:
      return 'process';
    case 200:
      return 'finish';
    case 500:
      return 'error';
  }
};

const handleMessage = (data) => {
  if (device.value[data.key]) {
    device.value[data.key].push(data);
  } else {
    device.value[data.key] = [data];
  }
};

const { connect, disconnect } = useEventSource(props.url, {
  headers: {
    ['Authorization']: `Bearer ${userStore.token}`,
    'Content-Type': 'application/json',
  },
  withCredentials: false,
  method: 'POST',
  body,
  onMessage(res) {
    const data = JSON.parse(res);
    handleMessage(data);
  },
});

const visible = ref<boolean>(false);
const onConnect = async () => {
  await props.beforeConnect();
  visible.value = true;
  connect();
};

const emit = defineEmits<{
  closeAfter: [];
}>();
const onCancel = () => {
  device.value = {};
  disconnect();
  emit('closeAfter');
};
</script>
